/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mygameframework.test;

import com.mygameframework.isoengine.TileWalker;
import com.mygameframework.isoengine.Direction;
import com.mygameframework.isoengine.MapType;
import com.mygameframework.isoengine.Scroller;
import com.mygameframework.isoengine.TilePlotter;
import com.mygameframework.util.Utility;
import com.mygameframework.core.GameCore;
import com.mygameframework.core.GeneralGameCore;
import com.mygameframework.core.input.GameAction;
import com.mygameframework.core.input.InputManager;
import com.mygameframework.isoengine.*;
import com.mygameframework.scenes.CommonScene;
import com.mygameframework.scenes.IRenderable;
import com.mygameframework.isoengine.TileSet;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.EnumSet;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 *
 * @author bill
 */
public class CustomScene1  extends CommonScene implements IRenderable{
    
    GameAction NORTH;
    GameAction EAST;
    GameAction SOUTH;
    GameAction WEST;
    GameAction SPACE;
//    boolean n,e,s,w;
    
    int tw,th;
    int mapWidth;
    int mapHeight;
    int screenWidth;
    int screenHeight;
    int dx,dy;
    /*
     * map 坐标
     */
    Point cursorAnchor=new Point();
    Point screenAnchorScroll=new Point();//是一个位移量
    Insets in;
    
    int Scroll_WHEN_BORDER_SIZE=20;
  /** Scroll increment. */
  private static final int SCROLL_INCREMENT_PER_SECOND = 360;
  
    public TileSet tileSet;
    public TileSet cursor;
    public TileSet unit;
    public int[][] mapArr;
    
    TilePlotter tp;
    TileWalker twk;
    Scroller scroller;
    
    Renderer renderer;
    TileEngine tengine;
    public CustomScene1(GeneralGameCore gameCore) {
        super(gameCore);
    }
    public static Point slideMap_TileWalker(Point pStart,Direction dir){
        Point tmp=new Point(pStart);
        switch (dir) {
            case NORTH:
                tmp.x++;
                tmp.y-=2;
                break;
            case NORTHEAST:
                tmp.x++;
                tmp.y--;
                break;
            case EAST:
                tmp.x++;
                break;
            case SOUTHEAST:
                tmp.y++;
                break;
            case SOUTH:
                tmp.x--;
                tmp.y+=2;
                break;
            case SOUTHWEST:
                tmp.x--;
                tmp.y++;
                break;
            case WEST:
                tmp.x--;
                break;
            case NORTHWEST:
                tmp.y--;
                break;
            default:
                throw new AssertionError();
        }
        return tmp;
    }

    /**move cursor point (map坐标)*/
    public void moveCursor(Direction dir){
        oldCursorAnchor.x=cursorAnchor.x;
        oldCursorAnchor.y=cursorAnchor.y;
//        Point ptTmp=twk.tileWalk(this.cursorAnchor,dir);
        renderer.addTile(cursorAnchor.x, cursorAnchor.y);
        //得到Map point
        Point ptTmp=tengine.getWalker().tileWalk(cursorAnchor, dir);

        //map bounds checks
        if(ptTmp.x<0 ||ptTmp.y<0 || ptTmp.x>(mapWidth-1) || ptTmp.y>(mapHeight-1)) 
            ptTmp=this.cursorAnchor;
        this.cursorAnchor=ptTmp;
//        System.out.println("[CustomScene1.moveCursor]walker after "+ptTmp);
//        Point ptPlot=tp.plotTile(ptTmp);
        Point ptPlot=tengine.getPlotter().plotTile(ptTmp);//map to world
//        System.out.println("plot "+ptPlot);
        //map to world
        ptPlot.translate(tengine.getOffsetX(), tengine.getOffsetY());
        int newAnchorX= (int) (ptPlot.x-tengine.getScreenSpace().getWidth()/2+tw/2);
        int newAnchorY=(int) (ptPlot.y-tengine.getScreenSpace().getHeight()/2+th/2);
        int dx=newAnchorX-tengine.getScreenAnchorX();
        int dy=newAnchorY-tengine.getScreenAnchorY();
        System.out.println("[CustomScene1.moveCursor] dx dy"+dx+" "+dy);
        renderer.scrollFrame(dx, dy);
        
        //make screenAchor keeps center in screen
//        tengine.getScroller().getScreenAnchor().x=
//                (int) (ptPlot.x-tengine.getScreenSpace().getWidth()/2+tw/2);
//        tengine.getScroller().getScreenAnchor().y=
//                (int) (ptPlot.y-tengine.getScreenSpace().getHeight()/2+th/2);
        
        //bounds checking for anchor
//        checkScreenAnchor();
    }
    private Point oldCursorAnchor=new Point();
    @Override
    public synchronized void mouseMoved(MouseEvent e) {

        //ptMouse 含有inset的值,
//        Point ptMouse=this.gameCore.getInputManager().getMousePosition();
        Point ptMouse=e.getPoint();
        //通过减insets值,得出相对于窗体内容面板的坐标
    //            ptMouse.x-=in.left;
    //            ptMouse.y-=in.top;
        if(tengine==null)return;
        Point ptMap=tengine.mouseMap(ptMouse);
        
//        Point ptMap=slideMap_MouseMapper(ptMouse, mmp,in.left,in.top);
        if(ptMap.x<0) ptMap.x=0;
        if(ptMap.y<0) ptMap.y=0;
        if(ptMap.x>tengine.getMapWidth()-1) ptMap.x=tengine.getMapWidth()-1;
        if(ptMap.y>tengine.getMapHeight()-1) ptMap.y=tengine.getMapHeight()-1;
//        System.out.println("pt map "+ptMap);
        oldCursorAnchor=cursorAnchor;
        this.cursorAnchor=ptMap;
        ptMouse=e.getPoint();
        screenAnchorScroll.x=0;
        screenAnchorScroll.y=0;
//        System.out.println("ptMouse "+ptMouse);
        if(ptMouse.x<in.left+Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.x = -(in.left+ Scroll_WHEN_BORDER_SIZE - ptMouse.x);
        }
        if(ptMouse.y<in.top+Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.y = -((in.top+Scroll_WHEN_BORDER_SIZE )-ptMouse.y );
        }
        if(ptMouse.x>tengine.getScreenSpace().getWidth()-Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.x = (int) (ptMouse.x
                    -(tengine.getScreenSpace().getWidth()-Scroll_WHEN_BORDER_SIZE));
        }
        if(ptMouse.y>tengine.getScreenSpace().getHeight()-Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.y= (int) (ptMouse.y
                    -(tengine.getScreenSpace().getHeight()-Scroll_WHEN_BORDER_SIZE));
        }

    }
    /**
     *
     * @param g2 不要调用Graphics.dispose(),这是系统的事情
     * @param givenRect 要渲染的区域(在screenSpace内)
     * @param dstX 打印的坐标X
     * @param dstY
     * @param ptMap 当前渲染到地图坐标哪点
     */
    @Override
    public void render(Graphics2D g2, Rectangle givenRect, int dstX, int dstY, Point ptMap) {
        this.tileSet.efficientPut(g2, givenRect, dstX, dstY,
                this.mapArr[ptMap.x][ptMap.y]);
        Point plot=tengine.getPlotter().plotTile(cursorAnchor);
        plot=tengine.getScroller().worldToScreen(plot);//代替下面手工计算
//        p.translate(tengine.getOffsetX(), tengine.getOffsetY());
        unit.efficientPut(g2,new Rectangle(plot.x,plot.y-60,64,128)
                ,plot.x,plot.y, 0);
        showIsoCursor(g2);
//        unit.put(g2, plot.x, plot.y,0);
        
        
    }
    public void setupMap(){
        mapArr=new int[mapWidth][mapHeight];
        Random rnd=new Random();
        for(int x=0;x<mapWidth;x++){
            for(int y=0;y<mapHeight;y++){
                mapArr[x][y]=rnd.nextInt(tileSet.getTileCount());
            }
        }
    }
    public void updateSpaces(){
        
        in=this.gameCore.getFrame().getInsets();
        this.screenWidth=this.gameCore.getFrame().getWidth()-in.left-in.right;
        this.screenHeight=this.gameCore.getFrame().getHeight()-in.top-in.bottom;
        dx=in.left;dy=in.top;
        //screen spce
        Rectangle screenSpace=new Rectangle(dx, dy,
                this.screenWidth,
                this.screenHeight);
        System.out.println("[scene1 updateSpace] screenspace "+screenSpace);
        
        tengine.reCalcOffsetAndAnchorSpace(screenSpace);
        
        renderer.addRect(tengine.getScreenSpace());
        
//        scroller.setScreeSpace(screenSpace);
//        scroller.calculateWorldSpace(tp, mapWidth, mapHeight);
//        scroller.calculateAnchorSpace();
        //anchor space
    }

    @Override
    public void enterFullScreen() {
        updateSpaces();
        System.out.println("enter update "+tengine.getScreenSpace());
        System.out.println("world space:"+tengine.getWorldSpace());
    }

    @Override
    public void exitFullScreen() {
        updateSpaces();
        System.out.println("exit update "+tengine.getScreenSpace());
        System.out.println("world space:"+tengine.getWorldSpace());
    }
    
    public void showIsoCursor(Graphics2D g){
        int cw=cursor.getInfos()[0].src.width;
        int ch=cursor.getInfos()[0].src.height;

//        Point p=slideMap_TilePlotter(cursorAnchor, cw, ch, dx, dy);
//        cursor.put(g, p.x-screenAnchor.x, p.y-screenAnchor.y, 0);
        Point p=tengine.getPlotter().plotTile(cursorAnchor);
        //plot=tengine.getScroller().worldToScreen(plot);代替下面手工计算
        p.translate(tengine.getOffsetX(), tengine.getOffsetY());
        cursor.put(g, p.x-tengine.getScreenAnchorX(),
                p.y-tengine.getScreenAnchorY(), 0);
    }
    @Override
    public void enter(GameCore entity) {
        super.enter(entity);
        
        Root root=(Root)entity;
        this.gameCore.getFrame().addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                super.keyReleased(e);
            }

            @Override
            public void keyTyped(KeyEvent e) {
                super.keyTyped(e);
            }
        });
        
        this.mapWidth=root.mapWidth;
        this.mapHeight=root.mapheight;
        
        // load - setupSpaces - setupMap
        tileSet=new TileSet(0x000000);
        cursor=new TileSet(0x000000);
        unit=new TileSet(0x000000);
        try {
            tileSet.load("images/IsoHex12_3-1.bmp");
            cursor.load("images/IsoHex12_3-2.bmp");
            unit.load("images/unit_warrior.bmp");
            unit.getInfos()[0].dstExt.setLocation(0,
                   -40);

            tw = tileSet.tileInfos[0].src.width;
            th = tileSet.tileInfos[0].src.height;
            
//            setupSpaces();
            setupMap();
            
            
            in = this.gameCore.getFrame().getInsets();
            this.screenWidth = this.gameCore.getFrame().getWidth() - in.left - in.right;
            this.screenHeight = this.gameCore.getFrame().getHeight() - in.top - in.bottom;
            dx = in.left;
            dy = in.top;
            //screen space 窗体显示区域(不计标题兰和边框),该区域应小于或等于窗体区域大小
            Rectangle screenSpace = new Rectangle(dx, dy,
                    this.screenWidth,
                    this.screenHeight);

            cursorAnchor.x = 0;
            cursorAnchor.y = 0;
            
            

            tengine=new TileEngine(screenSpace,tileSet.getInfos()[0].dstExt,
//                    MapType.MAP_SLIDE, 
//                    MapType.MAP_STAGGERED, 
                    MapType.MAP_DIAMOND, 
//                    MapType.MAP_RECTANGULAR, 
                    tw, th,
                    mapWidth, mapHeight,
//                    Scroller.SCROLLER_WRAP_MODE.WRAP_MODE_NONE, //h
//                    Scroller.SCROLLER_WRAP_MODE.WRAP_MODE_NONE);//v
//                    Scroller.SCROLLER_WRAP_MODE.WRAP_MODE_WRAP, //h
//                    Scroller.SCROLLER_WRAP_MODE.WRAP_MODE_WRAP);//v
                    Scroller.SCROLLER_WRAP_MODE.WRAP_MODE_CLIP, //h
                    Scroller.SCROLLER_WRAP_MODE.WRAP_MODE_CLIP);//v
            
            renderer=new Renderer(tengine,this);
            renderer.addRect(tengine.getScreenSpace());
                    
        } catch (IOException ex) {
            Logger.getLogger(CustomScene1.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public void drawMap(Graphics2D g){
//        int isWrap=Scroller.SCROLLER_WRAP_MODE.WRAP_MODE_WRAP==tengine.getScroller()
//                .g
                
        
//        r.efficientPaint(g);
        
        Point plot=new Point();
        Point map = new Point();
        dx=this.gameCore.getFrame().getInsets().left;
        dy=this.gameCore.getFrame().getInsets().top;
        int count = 0;
        for(int r=0;r<this.mapHeight;r++){
            for(int c=0;c<this.mapWidth;c++){
                map.x=c;
                map.y=r;
                plot=tengine.getPlotter().plotTile(map);//map to world//约占15ms 
                plot=tengine.getScroller().worldToScreen(plot);////clone占用大量时间
                
//                this.tileSet.put(g, plot.x /* -tengine.getScreenAnchorX()*/,
//                        plot.y /*- tengine.getScreenAnchorY()*/, mapArr[c][r]);
                
                boolean tf=this.tileSet.efficientPut(g, tengine.getScreenSpace(),plot.x, plot.y,
                            mapArr[c][r]);
                if(tf) count++ ;
//                g.setColor(Color.GRAY);
//                g.drawString(r+","+c, plot.x+20, plot.y+15);
            }
        }//for end
//        System.out.println("[customscene.drawMap]"+count);
    }
    
    @Override
    public synchronized void updateGame(long elapsedTime) {
//        n=NORTH.isPressed();
//        s=SOUTH.isPressed();
//        w=WEST.isPressed();
//        e=EAST.isPressed();
//        tengine.moveScreenAnchor(screenAnchorScroll.x, screenAnchorScroll.y,
//                true);
//            renderer.addTile(oldCursorAnchor.x,oldCursorAnchor.y);
        
                Point plot=tengine.getPlotter().plotTile(oldCursorAnchor);
        plot=tengine.getScroller().worldToScreen(plot);//代替下面手工计算
//        p.translate(tengine.getOffsetX(), tengine.getOffsetY());
        renderer.addRect(new Rectangle(plot.x,plot.y-60,64,128));
        
            renderer.addTile(cursorAnchor.x, cursorAnchor.y,new Rectangle(0,-40,32,128));
        renderer.addTile(oldCursorAnchor.x,oldCursorAnchor.y,new Rectangle(0,-40,32,128));
        renderer.scrollFrame(screenAnchorScroll.x, screenAnchorScroll.y);
//        checkScreenAnchor();
        //键盘事件处理
        if(NORTH.isPressed() && EAST.isPressed()){
            System.out.println("右上");
            moveCursor(Direction.NORTHEAST);
        }else if(EAST.isPressed() &&SOUTH.isPressed()){
            System.out.println("右下");
            moveCursor(Direction.SOUTHEAST);
        }else if( SOUTH.isPressed() && WEST.isPressed()){
            System.out.println("左下");
            moveCursor(Direction.SOUTHWEST);
        }else if(WEST.isPressed() && NORTH.isPressed()){
            System.out.println("左上");
            moveCursor(Direction.NORTHWEST);
        }else if(NORTH.isPressed()){
            System.out.println("上");
            moveCursor(Direction.NORTH);
        }else if(EAST.isPressed()){
            System.out.println("右");
            moveCursor(Direction.EAST);
        }else if(SOUTH.isPressed()){
            System.out.println("下");
            moveCursor(Direction.SOUTH);
        }else if(WEST.isPressed()){
            System.out.println("左");
            moveCursor(Direction.WEST);
        }
        if(isEnterPressed()){
            System.out.println("");
            System.out.println(""+unit.getInfos()[0].anchor);
            System.out.println(""+unit.getInfos()[0].dstExt);
//            System.out.println("enter:");
//            Frame f=this.gameCore.getFrame();
//            System.out.println("frame's insets:"+f.getInsets());
//            Point p=new Point(this.gameCore.getInputManager().getMouseX(),
//                    this.gameCore.getInputManager().getMouseY());
//            System.out.println("mouse anchor[in frame] :"+p);
//            Point point=MouseInfo.getPointerInfo().getLocation();
//            System.out.println("screen point : "+point);
//            SwingUtilities.convertPointFromScreen(point , 
//                this.gameCore.getFrame() );
//            System.out.println(""+point);
//            System.out.println("anchorSpace:"+tengine.getAnchorSpace());
//            System.out.println("worldSpace:"+tengine.getWorldSpace());
//            System.out.println("screenSpace:"+tengine.getScreenSpace());
//            System.out.println("screenAnchor:"+tengine.getScreenAnchor());
        }
        if(isMouseClick_button1()){
            System.out.println("");
            System.out.println("b1");
            

            
        }
        if(isbMouseClick_button3()){
            System.out.println("b3");
        }
        
        
        
    }
    /**
     * 在GameCore中offscreen(BufferedImage)的graphics2D
     * 上绘制
     * @param g GameCore中offscreen(BufferedImage)的graphics2D
     */
    @Override
    public synchronized void draw(Graphics2D g) {
        
        long startTime = System.nanoTime();
        //g是离屏图的graphics
//        g.setColor(Color.WHITE);
//        g.fill(tengine.getScreenSpace());
//        g.fillRect(tengine.getScreenSpace().x,
//               tengine.getScreenSpace().y,
//               tengine.getScreenSpace().width,
//               tengine.getScreenSpace().height);
        
//        drawMap(g);
//        renderer.efficientPaint(g);//renderer 调用 scene.render()方法
        renderer.updateFrame(); //renderer.scrollFrame 一起使用
        
//        showIsoCursor(g);
        
//        g.setColor(Color.RED);
//        g.draw(screenSpace);
        
//        g.drawRect(screenSpace.x, screenSpace.y, screenSpace.width-1,
//                screenSpace.height-1);
//        g.setColor(Color.BLACK);
//        g.drawRect(anchorSpace.x, anchorSpace.y, anchorSpace.width-1,
//                anchorSpace.height-1);
        long stopTime = System.nanoTime();
//        System.out.println("[CustomScene.draw]Painted in " + 
//                ((stopTime - startTime) / 1000000) + " ms");
    }

    @Override
    public void createGameActions() {
        System.out.println("create game action");
        NORTH=new GameAction("上",GameAction.BEHAVIOR_VARIETY);
        SOUTH=new GameAction("下",GameAction.BEHAVIOR_VARIETY);
        WEST=new GameAction("左",GameAction.BEHAVIOR_VARIETY);
        EAST=new GameAction("右",GameAction.BEHAVIOR_VARIETY);
        SPACE=new GameAction("空格",GameAction.BEHAVIOR_VARIETY);
        InputManager input=this.gameCore.getInputManager();
        input.mapToKey(NORTH,KeyEvent.VK_UP);
        input.mapToKey(EAST,KeyEvent.VK_RIGHT);
        input.mapToKey(SOUTH,KeyEvent.VK_DOWN);
        input.mapToKey(WEST,KeyEvent.VK_LEFT);
        input.mapToKey(SPACE,KeyEvent.VK_SPACE);
    }

    @Override
    public void createSystemActions() {
        super.createSystemActions();
//        throw new UnsupportedOperationException("Not supported yet.");
    }


    @Override
    public void checkSystemInput() {
        super.checkSystemInput();
        if(isEnterPressed()){
//            System.out.println("world space "+worldSpace);
//            System.out.println("screen space "+screenSpace);
//            System.out.println("anchor space "+anchorSpace);
        }
        if(pause.isPressed()){
            setPaused(!isPaused());
        }
    }
    public void checkScreenAnchor(){
        tengine.getScroller().warpAnchor();
//        if(screenAnchor.x<anchorSpace.x) screenAnchor.x=anchorSpace.x;
//        if(screenAnchor.x>anchorSpace.getMaxX()) screenAnchor.x=(int) anchorSpace.getMaxX();
//        if(screenAnchor.y<anchorSpace.y) screenAnchor.y=anchorSpace.y;
//        if(screenAnchor.y>anchorSpace.getMaxY()) screenAnchor.y=(int) anchorSpace.getMaxY();
    }
    public static void main(String[] args) throws IOException {
        int mapWidth=40;
        int mapHeight=80;
        TileSet tileSet=new TileSet(0x000000);
        tileSet.load("images/IsoHex12_2.bmp");
        Rectangle screenSpace=new Rectangle(0, 0, 640, 400);
        
        int tw=tileSet.tileInfos[0].src.width;
        int th=tileSet.tileInfos[0].src.height;
        Rectangle t1=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
	Rectangle t2=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
//	Point plot;
//        Point map=new Point(0, 0);
//        plot=slideMap_TilePlotter(map,tw,th);
//        t1.translate(plot.x, plot.y);
//        map=new Point(mapWidth-1, mapHeight-1);
//        plot=slideMap_TilePlotter(map,tw,th);
//        t2.translate(plot.x, plot.y);
//        Rectangle w=t1.union(t2);
//        System.out.println(t2);
//        System.out.println("w "+w);
    }

    @Override
    public Graphics2D getOffScreenGraphics() {
        return getGameCore().getOffscreenGraphics();
    }

    @Override
    public BufferedImage getOffScreenImage() {
        return getGameCore().getOffscreenBufferedImage();
    }
}
